package com.example.JavaWebApi.service.impl.systemImpl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.JavaWebApi.core.commonmodel.Exceptions.BusinessException;
import com.example.JavaWebApi.core.commonmodel.ResponseTypeEnum;
import com.example.JavaWebApi.core.reflect.ReflectionHelper;
import com.example.JavaWebApi.mapper.systemMapper.MenuinfoMapper;
import com.example.JavaWebApi.model.entity.systemEntity.Dictionary;
import com.example.JavaWebApi.model.entity.systemEntity.Menuinfo;
import com.example.JavaWebApi.service.systemService.IDictionaryService;
import com.example.JavaWebApi.service.systemService.IMenuinfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 杨泽
 * @since 2022-06-15
 */
@Service
public class MenuinfoServiceImpl extends ServiceImpl<MenuinfoMapper, Menuinfo> implements IMenuinfoService {
    @Autowired
    private IDictionaryService dictionaryService;
    private static final Object lock = new Object();
    @Override
    public List<Menuinfo> getMenuTree() {
        QueryWrapper<Menuinfo> queryWrapper=new QueryWrapper<>();
        //queryWrapper.eq("MenuType","menu");
        queryWrapper.orderByAsc("MenuSortNo");
        List<Menuinfo> source=this.baseMapper.selectList(queryWrapper);
        source.forEach(t->t.setButton(t.getMenuType().equals("button")));
        source= ReflectionHelper.convertToTreeList(source,t->t.getMenuParentId()==null||t.getMenuParentId()==0,t->t.getId(),t->t.getMenuParentId(),Menuinfo.class);
        return source;
    }

    @Override
    public IPage<Menuinfo> getLazyList(Integer parentId, int page, int limit) {
        QueryWrapper<Menuinfo> queryWrapper=new QueryWrapper<>();
        queryWrapper.select("*," +"(select name from sys_dictionary sub where sys_menuinfo.MenuType=sub.`Value` and sub.ParentId=9) as MenuTypeName,"+
                        "(case when exists(select 1 from sys_menuinfo sub where sub.MenuParentId=sys_menuinfo.Id) then 1 else 0 end) as hasChildren")
                .orderByAsc("MenuSortNo");
        if (parentId==null||parentId.equals(0)){
            IPage<Menuinfo> pageModel=new Page<>(page,limit);
            queryWrapper.apply("MenuParentId is null or MenuParentId=0");
            return this.baseMapper.selectPage(pageModel,queryWrapper);
        }
        else {
            IPage<Menuinfo> pageModel=new Page<>(page,limit);
            queryWrapper.eq("MenuParentID",parentId);
            return this.baseMapper.selectPage(pageModel,queryWrapper);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean create(Menuinfo menuinfo) {
        synchronized (lock){
            checkMenu(menuinfo);
            this.baseMapper.insert(menuinfo);
            if(menuinfo.getMenuType().equals("menu")){
                List<Dictionary> dictionaryList= dictionaryService.getListByParentId(2);
                List<Menuinfo> buttons=new ArrayList<>();
                menuinfo.getButtonKeys().forEach(t->{
                    dictionaryList.stream()
                            .filter(x->x.getValue().equals(t))
                            .findFirst()
                            .ifPresent(x->{
                                Menuinfo button=new Menuinfo();
                                button.setMenuParentId(menuinfo.getId());
                                button.setMenuType("button");
                                button.setIsUse(1);
                                button.setIsHidden(0);
                                button.setMenuName(x.getName());
                                button.setMenuKey(x.getValue());
                                buttons.add(button);
                            });
                });
                if(!buttons.isEmpty()){
                    saveBatch(buttons);
                }
            }
            return true;
        }
    }

    @Override
    public boolean update(Menuinfo menuinfo) {
        synchronized (lock){
            checkMenu(menuinfo);
            return this.baseMapper.updateById(menuinfo)>0;
        }
    }

    @Override
    public boolean delete(Integer id) {
        return this.baseMapper.deleteById(id)>0;
    }
    private void checkMenu(Menuinfo menuinfo){
        if(menuinfo.getMenuParentId()==null || menuinfo.getMenuParentId()==0){
            if(menuinfo.getMenuType().equals("button")){
                throw new BusinessException(ResponseTypeEnum.Exception,"根节点下不允许创建按钮！");
            }
        }else {
            Menuinfo parent= this.baseMapper.selectById(menuinfo.getMenuParentId());
            if(parent==null){
                throw new BusinessException(ResponseTypeEnum.Exception,"非法父节点！");
            }
            if(parent.getId().equals(menuinfo.getId())){
                throw new BusinessException(ResponseTypeEnum.Exception,"禁止自己作为自己的父节点！");
            }
            if(parent.getMenuType().equals("button")){
                throw new BusinessException(ResponseTypeEnum.Exception,"按钮节点下不允许创建任何节点");
            }
            if(parent.getMenuType().equals("directory")&&menuinfo.getMenuType().equals("button")){
                throw new BusinessException(ResponseTypeEnum.Exception,"目录下不允许创建按钮！");
            }
            if(parent.getMenuType().equals("menu") && !menuinfo.getMenuType().equals("button")){
                throw new BusinessException(ResponseTypeEnum.Exception,"菜单下只允许创建按钮！");
            }
        }
    }
    @Override
    public List<Integer> getMenuByRoleId(Integer roleId) {
        return this.baseMapper.getMenuByRoleId(roleId);
    }

    @Override
    public List<Menuinfo> getMenuByUserId(Integer userId) {
        QueryWrapper<Menuinfo> queryWrapper=new QueryWrapper<>();
        queryWrapper.orderByAsc("MenuSortNo");
        if (!userId.equals(-9999)){
            queryWrapper.eq("e.Id",userId)
                    .eq("a.IsUse",1);
            return this.baseMapper.getMenuByUserId(queryWrapper);
        }
        else {
            return this.baseMapper.selectList(queryWrapper);
        }

    }
}
